package com.collectionutils;

import com.bean.User;
import com.google.common.collect.*;
import org.junit.Test;

import java.util.List;
import java.util.Map;

public class MapsDemo {


    /**
     * Maps类有若干值得单独说明的、很酷的方法
     */
    @Test
    public void mapsDemo(){
        List<String> list = Lists.newArrayList("hou", "zheng", "ha","haha");
        /**
         * uniqueIndex: 根据集合中某一个独一无二的属性返回一个map,键是Function的值,value是集合中数据
         *  比如,根据value中字符串length,返回一个length - value map
         *  注意: 有两个value属性相同会报错,比如length都是2报错
         */
        Maps.uniqueIndex(list, String::length).forEach((x, y)-> System.out.println(x+", "+y));
        /**
         * 3, hou
         * 5, zheng
         * 2, ha
         * 4, haha
         */
        Map<String, Integer> map01 = Maps.newHashMap();
        map01.put("k1",1);
        map01.put("k2",2);
        Map<String, Integer> map02 = Maps.newHashMap();
        map02.put("k1",5);
        map02.put("k2",2);
        map02.put("k3",3);
        /**
         * 用来比较两个Map以获取所有不同点和不同点,返回MapDifference视图,可以获取各种数据
         */
        MapDifference<String, Integer> difference = Maps.difference(map01, map02);
        //获取键值都相同的key,value
        difference.entriesInCommon()
                .forEach((x,y)-> System.out.println(x+", "+y));//k2, 2
        //获取键相同但是值不同值的k,v
        difference.entriesDiffering();//k1, (1, 5)
        //获取键只在于左边Map的映射项
        difference.entriesOnlyOnLeft(); //没有
        //键只存在于右边Map的映射项
        difference.entriesOnlyOnRight();//k3, 3
    }

    /**
     *  处理BiMap,也在Maps里面
     */
    @Test
    public void btMapsTest(){
        BiMap<Integer, String> hashBiMap = HashBiMap.create();
        hashBiMap.put(1,"用户1");
        hashBiMap.put(2,"用户2");
        hashBiMap.put(3,"用户3");
        //返回一个线程同步的BiMap
        Maps.synchronizedBiMap(hashBiMap);
        //返回不可修改的BiMap
        BiMap<Integer, String> biMap = Maps.unmodifiableBiMap(hashBiMap);
    }

    /**
     * Multisets
     */
    @Test
    public void multisetsTest(){
        HashMultiset<Integer> superSet = HashMultiset.create();
        superSet.add(2,3);
        superSet.add(1,2);
        HashMultiset<Integer> subSet = HashMultiset.create();
        subSet.add(2,4);
        // 对任意o，如果sub.count(o)<= super.count(o)，返回true,
        // 即sub中的任意元素在super中有,并且重复的元素个数小于等于super
        Multisets.containsOccurrences(superSet, subSet);
        //移除superSet中所有在subSet中有的元素
        Multisets.removeOccurrences(superSet,subSet);
        superSet.forEach(System.out::println);
        //修改superSet,使修改superSet 成为subSet的子集(包含重复元素)
        Multisets.retainOccurrences(superSet,subSet);
        superSet.forEach(System.out::println);
        //返回两个set的交集
        Multiset<Integer> integers = Multisets.intersection(superSet, subSet);
        integers.forEach(System.out::println);
        //返回不可变copy,并按照重复次数降序排序
        ImmutableMultiset<Integer> immutableMultiset = Multisets.copyHighestCountFirst(superSet);
        immutableMultiset.forEach(System.out::println);
    }

    /**
     * Multimaps
     */
    @Test
    public void multimapsTest(){
        List<String> list = Lists.newArrayList("hou","yao", "zheng","haha","zhen");
        /**
         * 根据共同属性对集合分组,返回map,键是属性值(比如长度),value是值,可允许重复元素
         */
        System.out.println(Multimaps.index(list, String::length));
        //3=[hou, yao], 5=[zheng], 4=[haha, zhen]}

        Multimap<String, User> multimap = ArrayListMultimap.create();
        for (int i = 1; i <= 5; i++) {
            multimap.put("one",User.of().setAge(23).setName("用户"+i).setLevel(i));
        }
        for (int i = 1; i <= 5; i++) {
            multimap.put("two",User.of().setAge(20).setName("用户"+i).setLevel(i));
        }
        //反转Multimap,一个k多个v 反转为 多个k 映射一个v
        Multimap<User, String> userStringMultimap = Multimaps.invertFrom(multimap, ArrayListMultimap.create());
        userStringMultimap.forEach((x,y)-> System.out.println(x+","+y));
        /**
         *  forMap(Map)把Map包装成SetMultimap。这个方法特别有用
         *  可以使map使用Multimap的方法
         */
        Map<String, Integer> map = ImmutableMap.of("a", 1, "b", 1, "c", 2);//多对一
        SetMultimap<String, Integer> mapTomultimap = Multimaps.forMap(map);
        //将多对一转换为一对多
        Multimap<Integer, String> inverse = Multimaps.invertFrom(mapTomultimap, HashMultimap.create());
        System.out.println(inverse);//  {1=[a, b], 2=[c]}
    }
}
